package com.rayboot.footpoint.utils.voice;

import java.io.File;
import java.io.IOException;

import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;

public class Recorder implements MediaPlayer.OnCompletionListener,
		MediaPlayer.OnErrorListener {
	public static final int IDLE_STATE = 0;
	public static final int RECORDING_STATE = 1;
	public static final int PLAYING_STATE = 2;
	public static final int PAUSE_STATE = 3;
	public static final int NO_ERROR = 0;
	public static final int SDCARD_ACCESS_ERROR = 1;
	public static final int INTERNAL_ERROR = 2;
	static final String SAMPLE_EXTENSION = ".amr";
	static final String SAMPLE_LENGTH_KEY = "sample_length";
	static final String SAMPLE_PATH_KEY = "sample_path";
	static final String SAMPLE_PREFIX = "footpoint";
	static final String TAG = "Recorder";

	OnStateChangedListener mOnStateChangedListener = null;
	MediaPlayer mPlayer = null;
	MediaRecorder mRecorder = null;
	File mSampleFile = null;
	public int mSampleLength = 0;
	long mSampleStart = 0L;
	int mState = 0;

	public Recorder() {
	}

	public Recorder(File file) {
		mSampleFile = file;
	}

	public Recorder(String filePath) {
		if (filePath == null)
			return;

		if (!filePath.equalsIgnoreCase("")) {
			File localFile = new File(filePath);

			if (!localFile.exists()) {
				return;
			}

			mSampleFile = localFile;
			try {
				MediaPlayer mediaPlayer = new MediaPlayer();
				mediaPlayer.reset();
				mediaPlayer.setDataSource(mSampleFile.getAbsolutePath());
				mediaPlayer.prepare();
				mSampleLength = mediaPlayer.getDuration();
				mediaPlayer.release();
			} catch (IllegalArgumentException localIllegalArgumentException) {
				localIllegalArgumentException.printStackTrace();
			} catch (IllegalStateException localIllegalStateException) {
				localIllegalStateException.printStackTrace();
			} catch (IOException localIOException) {
				localIOException.printStackTrace();
			}
		}
	}

	private void setError(int paramInt) {
		if (mOnStateChangedListener != null)
			mOnStateChangedListener.onError(paramInt);
	}

	private void setState(int state) {
		if (state == mState) {
			return;
		}

		mState = state;
		signalStateChanged(mState);
	}

	private void signalStateChanged(int state) {
		if (mOnStateChangedListener != null)
			mOnStateChangedListener.onStateChanged(state);
	}

	public void clear() {
		stop();
		mSampleLength = 0;
		signalStateChanged(IDLE_STATE);
	}

	public void delete() {
		stop();
		if (mSampleFile != null) {
			mSampleFile.delete();
		}
		mSampleFile = null;
		mSampleLength = 0;
		signalStateChanged(IDLE_STATE);
	}

	public long getDuration() {
		if (mPlayer == null) {
			return -1L;
		} else {
			return mPlayer.getDuration();
		}
	}

	public int getMaxAmplitude() {
		if (mState != 1) {
			return 0;
		} else {
			return mRecorder.getMaxAmplitude();
		}
	}

	public int progress() {
		if (mState == RECORDING_STATE || mState == PLAYING_STATE) {
			return (int) (System.currentTimeMillis() - mSampleStart);
		}
		return 0;
	}

	public void restoreState(Bundle bundle) {
		String filePath = bundle.getString(SAMPLE_PATH_KEY);
		if (filePath == null) {
			return;
		}

		int length = bundle.getInt(SAMPLE_LENGTH_KEY, -1);
		if (length == -1) {
			return;
		}

		File file = new File(filePath);
		if (!file.exists()
				|| (mSampleFile != null && mSampleFile.getAbsolutePath()
						.compareTo(file.getAbsolutePath()) == 0)) {
			return;
		}

		delete();
		mSampleFile = file;
		mSampleLength = length;
		signalStateChanged(IDLE_STATE);
	}

	public File sampleFile() {
		return mSampleFile;
	}

	public int sampleLength() {
		return mSampleLength;
	}

	public void saveState(Bundle bundle) {
		bundle.putString(SAMPLE_PATH_KEY, mSampleFile.getAbsolutePath());
		bundle.putInt(SAMPLE_LENGTH_KEY, mSampleLength);
	}

	public void setOnStateChangedListener(OnStateChangedListener listener) {
		mOnStateChangedListener = listener;
	}

	public void startPlayback() {
		stop();
		mPlayer = new MediaPlayer();
		try {
			mPlayer.setDataSource(mSampleFile.getAbsolutePath());
			mPlayer.setOnCompletionListener(this);
			mPlayer.setOnErrorListener(this);
			mPlayer.prepare();
			mSampleLength = mPlayer.getDuration();
			mPlayer.start();
			mSampleStart = System.currentTimeMillis();
			setState(PLAYING_STATE);
			return;
		} catch (IllegalArgumentException localIllegalArgumentException) {
			setError(INTERNAL_ERROR);
			mPlayer = null;
		} catch (IOException localIOException) {
			setError(SDCARD_ACCESS_ERROR);
			mPlayer = null;
		}
	}

	@Override
	public boolean onError(MediaPlayer mp, int arg1, int arg2) {
		// TODO Auto-generated method stub
		stop();
		setError(SDCARD_ACCESS_ERROR);
		return true;
	}

	@Override
	public void onCompletion(MediaPlayer mp) {
		// TODO Auto-generated method stub
		setState(IDLE_STATE);
		stop();
	}

	public void startRecording() {
		stop();
		File file = null;
		if (mSampleFile == null) {
			file = new File(FootprintVoiceManager.getDirectory());
			if (!file.exists()) {
				file.mkdirs();
			}

			if (!file.canWrite()) {
				file = new File(Environment.getExternalStorageDirectory()
						.toString());
			}
		}

		try {
			mSampleFile = File.createTempFile(SAMPLE_PREFIX, SAMPLE_EXTENSION,
					file);
			mRecorder = new MediaRecorder();
			mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
			mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
			mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
			mRecorder.setOutputFile(mSampleFile.getAbsolutePath());
			mRecorder.prepare();
			mRecorder.start();
			mSampleStart = System.currentTimeMillis();
			setState(RECORDING_STATE);
		} catch (IOException localIOException1) {
			setError(SDCARD_ACCESS_ERROR);
		}
	}

	public int state() {
		return mState;
	}

	public void stop() {
		stopRecording();
		stopPlayback();
	}

	public void stopPlayback() {
		if (mPlayer == null) {
			return;
		}

		mPlayer.stop();
		mPlayer.release();
		mPlayer = null;
		setState(IDLE_STATE);
	}

	public void stopRecording() {
		if (mRecorder == null) {
			return;
		}

		mRecorder.stop();
		mRecorder.release();
		mRecorder = null;
		mSampleLength = (int) (System.currentTimeMillis() - mSampleStart);
		setState(IDLE_STATE);
	}

	public static abstract interface OnStateChangedListener {
		public abstract void onError(int errorCode);

		public abstract void onStateChanged(int state);
	}
}
